from users.serializers import UserSerializer
from django.contrib.auth import get_user_model
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from django.shortcuts import redirect
from django.http import HttpResponse, JsonResponse
# ⬇ 取数据库里的 user 表，验证用户名和登录密码
from django.contrib.auth import authenticate
from django.contrib.auth import login
# ⬆ 调用自带 login 方法，生成用户名和密码，并保存，实现免密登录
from django.contrib.auth import logout
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.authentication import SessionAuthentication
from rest_framework import status
from django.contrib.auth.hashers import check_password
from rest_framework_jwt.settings import api_settings
from users.models import Users
from django.shortcuts import render, redirect
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from django.conf import settings
from django.core.urlresolvers import reverse
from celery_tasks.tasks import send_register_active_email
User = get_user_model()


# =============================== ⬇        django 函数视图        ⬇ ===============================================
def user_login(request):
    username = request.POST['username']
    password = request.POST['password']
    remember = request.POST.get('remember')
    try:
        user = authenticate(username=username, password=password)

    except:
        return HttpResponse('账号或密码错误')
    if user is not None:

        if user.is_active == 1:
            login(request, user)
            # ⬆ 用于 set session

            # 设定 cookie
            response = redirect(reverse('comic_index'))

            # 判断用户是否选择记住用户名
            if remember == 'on':
                response.set_cookie('username', username, max_age=3600*24*7)

            else:
                response.delete_cookie('username')

            return response

        else:
            url_source = request.META['HTTP_REFERER']

            return redirect(url_source)

    else:
        return redirect(reverse('comic_index'))


def user_logout(request):
    logout(request)
    url_source = request.META['HTTP_REFERER']

    return redirect(url_source)


def user_register(request):
    username = request.POST['username']
    password = request.POST['password']
    cpassword = request.POST['cpassword']
    email = request.POST['email']

    if not all([username, password, cpassword, email]):
        return HttpResponse('账号或密码不能为空')

    if len(password) < 8:
        return HttpResponse('密码长度不能小于8位')

    if password != cpassword:
        return HttpResponse('两次密码不相同')

    try:
        user = User.objects.get(username=username)
    except Exception:
        user = None

    if user:
        return render(request, 'index.html', {'errormsg': '用户已存在'})

    user = User.objects.create_user(username=username, password=password, email=email)
    # ⬆ 调用 create_user 方法加密生成密码
    user.is_active = 0
    user.save()
    serializer = Serializer(settings.SECRET_KEY, 3600)
    user_info = {'confirm': user.id}
    # 生成token
    token = serializer.dumps(user_info)
    token = token.decode()
    send_register_active_email.delay(email, username, token)

    url_source = request.META['HTTP_REFERER']
    return redirect(url_source)


def active(request, token):
    serializer = Serializer(settings.SECRET_KEY, 3600)

    try:
        info = serializer.loads(token)
        # 获取待激活用户的id
        user_id = info['confirm']

        # 根据id获取用户信息
        user = User.objects.get(id=user_id)
        user.is_active = 1
        user.save()

         # 跳转到登录页面
        return redirect(reverse('comic_index'))
    except Exception as e:
        # 激活链接已过期
        return HttpResponse('激活链接已过期')


# 注册用户名验证
def check_username(request):
    # 获取用户名
    username = request.POST['username']

    try:
        # 查询用户名是否存在
        user = Users.objects.get(username=username)
        # 如果存在返回数字1
        return JsonResponse({'res': 1})
    except Exception:
        # 如果抛出异常，说明用户名不存在，返回数字0
        return JsonResponse({'res': 0})


# 登录验证
def login_check(request):
    # 获取用户名
    username = request.POST['username']
    # 查询用户名是否存在
    try:
        user = Users.objects.get(username=username)
        # 如果用户存在，查询is_active的值，为0表示未激活，1表示激活
        if user.is_active == 0:
            return JsonResponse({'res': 0})
        elif user.is_active == 1:
            return JsonResponse({'res': 1})
    except Exception:

        return JsonResponse({'res': 2})


# =============================== ⬆        django 函数视图        ⬆ ===============================================

# =============================== ⬇  django rest framework 框架  ⬇ ===============================================

# class UserView(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin,
#                GenericViewSet):
#     """
#     create:
#         创建用户
#     list:
#         显示所有用户
#     retrieve:
#         显示单个用户
#     destroy:
#         删除单个用户
#     """
#     queryset = User.objects.all()
#     serializer_class = UserSerializer


class UserLogin(APIView):
    """
    APIView 用户登录
    """

    # TODO --> 开启后，报错 'CSRFCheck' object has no attribute 'process_request'

    # ⬇ 认证用户
    # authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)

    def post(self, request):
        from rest_framework_jwt.settings import api_settings

        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        user = User.objects.all()[0]
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        return Response(token)


class UserTokenViewSet(mixins.CreateModelMixin, GenericViewSet):
    """
    token 用户登录
    """

    queryset = User.objects.all()
    serializer_class = UserSerializer

    # ⬇ 定制 create 方法，进行登录验证
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        data = serializer.data

        username = data['username']
        password = data['password']

        try:
            user = User.objects.filter(username=username)[0]
        except:
            return Response('该用户不存在', status=status.HTTP_400_BAD_REQUEST)

        # ⬇ 密码为 hash 加密，调用 check_password 方法，从数据库取密码，进行验证
        if not check_password(password, user.password):
            return Response('密码错误', status=status.HTTP_400_BAD_REQUEST)

        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        headers = self.get_success_headers(serializer.data)
        return Response(token, status=status.HTTP_200_OK, headers=headers)


class UserViewSet(mixins.CreateModelMixin, GenericViewSet):
    """
    token 创建用户
    """

    # TODO --> 用户注册时，系统生成一个六位随机验证码，保存到数据库，并发送至邮箱
    # TODO --> 注册时需要账号，密码，邮箱，验证码，进行验证

    queryset = User.objects.all()
    serializer_class = UserSerializer

    # ⬇ 定制 create 方法，获取 token，用于注册后跳转登录
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)

        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        return Response(token, status=status.HTTP_201_CREATED, headers=headers)

    # ⬇ 定制 perform_create 方法，使用 AbstractUser 里自带的 create_user 方法，创建用户，并加密密码
    def perform_create(self, serializer):
        username = serializer.data['username']
        password = serializer.data['password']
        email = serializer.data['email']
        user = User.objects.create_user(username=username, password=password, email=email)
        return user


# TODO --> 在退出登录或修改密码时，使 JWT Token 失效
# TODO --> nginx 部署
# =============================== ⬆  django rest framework 框架  ⬆ ===============================================